/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002-2006
* Sleepycat Software. All rights reserved.
*
* $Id: MemoryBudget.java,v 1.1 2006/05/06 09:00:26 ckaestne Exp $
*/
package com.sleepycat.je.dbi;
import java.util.Iterator;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.EnvironmentStats;
import com.sleepycat.je.StatsConfig;
import com.sleepycat.je.config.EnvironmentParams;
import com.sleepycat.je.latch.LatchSupport;
import com.sleepycat.je.tree.BIN;
import com.sleepycat.je.tree.DBIN;
import com.sleepycat.je.tree.DIN;
import com.sleepycat.je.tree.IN;
/**
* MemoryBudget calculates the available memory for JE and how to apportion
* it between cache and log buffers. It is meant to centralize all memory
* calculations. Objects that ask for memory budgets should get settings from
* this class, rather than using the configuration parameter values directly.
*/
public class MemoryBudget implements EnvConfigObserver {
/*
* Object overheads. These are set statically with advance measurements.
* Java doesn't provide a way of assessing object size dynamically. These
* overheads will not be precise, but are close enough to let the system
* behave predictably.
*
* _32 values are the same on Windows and Solaris.
* _64 values are from 1.5.0_05 on Solaris.
* _14 values are from 1.4.2 on Windows and Solaris.
* _15 values are from 1.5.0_05 on Solaris and Windows.
*
* Specifically:
*
* java.vm.version=1.5.0_05_b05 os.name=SunOS
* java.vm.version=1.4.2_05_b04 os.name=SunOS
* java.vm.version=1.5.0_04_b05, os.name=Windows XP
* java.vm.version=1.4.2_06-b03, os.name=Windows XP
*
* The integer following the // below is the Sizeof argument used to
* compute the value.
*/
// 7
private final static int LONG_OVERHEAD_32 = 16;
private final static int LONG_OVERHEAD_64 = 24;
// 8 - 2560
private final static int BYTE_ARRAY_OVERHEAD_32 = 16;
private final static int BYTE_ARRAY_OVERHEAD_64 = 24;
// 2
private final static int OBJECT_OVERHEAD_32 = 8;
private final static int OBJECT_OVERHEAD_64 = 16;
// (4 - BYTE_ARRAY_OVERHEAD_32) / 256
private final static int ARRAY_ITEM_OVERHEAD_32 = 4;
private final static int ARRAY_ITEM_OVERHEAD_64 = 8;
// 20
private final static int HASHMAP_OVERHEAD_32 = 120;
private final static int HASHMAP_OVERHEAD_64 = 216;
// 21 - OBJECT_OVERHEAD_32 - HASHMAP_OVERHEAD_32
private final static int HASHMAP_ENTRY_OVERHEAD_32 = 24;
private final static int HASHMAP_ENTRY_OVERHEAD_64 = 48;
// 22
private final static int HASHSET_OVERHEAD_32 = 136;
private final static int HASHSET_OVERHEAD_64 = 240;
// 23 - OBJECT_OVERHEAD_32 - HASHSET_OVERHEAD_32
private final static int HASHSET_ENTRY_OVERHEAD_32 = 24;
private final static int HASHSET_ENTRY_OVERHEAD_64 = 48;
// 2 * HASHMAP_OVERHEAD_32
private final static int TWOHASHMAPS_OVERHEAD_32 = 240;
private final static int TWOHASHMAPS_OVERHEAD_64 = 432;
// 34
private final static int TREEMAP_OVERHEAD_32 = 40;
private final static int TREEMAP_OVERHEAD_64 = 64;
// 35 - OBJECT_OVERHEAD_32 - TREEMAP_OVERHEAD_32
private final static int TREEMAP_ENTRY_OVERHEAD_32 = 32;
private final static int TREEMAP_ENTRY_OVERHEAD_64 = 53;
// 9
private final static int LN_OVERHEAD_32 = 24;
private final static int LN_OVERHEAD_64 = 32;
// 19
private final static int DUPCOUNTLN_OVERHEAD_32 = 24;
private final static int DUPCOUNTLN_OVERHEAD_64 = 40;
// 12
private final static int BIN_FIXED_OVERHEAD_32_14 = 344;
private final static int BIN_FIXED_OVERHEAD_32_15 = 360;
private final static int BIN_FIXED_OVERHEAD_64_15 = 528;
// 18
private final static int DIN_FIXED_OVERHEAD_32_14 = 352;
private final static int DIN_FIXED_OVERHEAD_32_15 = 360;
private final static int DIN_FIXED_OVERHEAD_64_15 = 536;
// 17
private final static int DBIN_FIXED_OVERHEAD_32_14 = 352;
private final static int DBIN_FIXED_OVERHEAD_32_15 = 368;
private final static int DBIN_FIXED_OVERHEAD_64_15 = 544;
// 13
private final static int IN_FIXED_OVERHEAD_32_14 = 312;
private final static int IN_FIXED_OVERHEAD_32_15 = 320;
private final static int IN_FIXED_OVERHEAD_64_15 = 472;
// 6
private final static int KEY_OVERHEAD_32 = 16;
private final static int KEY_OVERHEAD_64 = 24;
// 24
private final static int LOCK_OVERHEAD_32 = 32;
private final static int LOCK_OVERHEAD_64 = 56;
// 25
private final static int LOCKINFO_OVERHEAD_32 = 16;
private final static int LOCKINFO_OVERHEAD_64 = 32;
/*
* Txn memory is the size for the Txn + a hashmap entry
* overhead for being part of the transaction table.
*/
// 15
private final static int TXN_OVERHEAD_32_14 = 167;
private final static int TXN_OVERHEAD_32_15 = 175;
private final static int TXN_OVERHEAD_64_15 = 293;
// 26
private final static int CHECKPOINT_REFERENCE_SIZE_32_14 = 32 +
HASHSET_ENTRY_OVERHEAD_32;
private final static int CHECKPOINT_REFERENCE_SIZE_32_15 = 40 +
HASHSET_ENTRY_OVERHEAD_32;
private final static int CHECKPOINT_REFERENCE_SIZE_64_15 = 56 +
HASHSET_ENTRY_OVERHEAD_64;
/* The per-log-file bytes used in UtilizationProfile. */
// 29 / 500
private final static int UTILIZATION_PROFILE_ENTRY_32 = 88;
private final static int UTILIZATION_PROFILE_ENTRY_64 = 136;
/* Tracked File Summary overheads. */
// 31
private final static int TFS_LIST_INITIAL_OVERHEAD_32 = 464;
private final static int TFS_LIST_INITIAL_OVERHEAD_64 = 504;
// 30
private final static int TFS_LIST_SEGMENT_OVERHEAD_32 = 440;
private final static int TFS_LIST_SEGMENT_OVERHEAD_64 = 464;
// 33
private final static int LN_INFO_OVERHEAD_32 = 24;
private final static int LN_INFO_OVERHEAD_64 = 48;
/* Approximate element size in an ArrayList of Long. */
// (28 - 27) / 100
private final static int LONG_LIST_PER_ITEM_OVERHEAD_32 = 20;
private final static int LONG_LIST_PER_ITEM_OVERHEAD_64 = 32;
public final static int LONG_OVERHEAD;
public final static int BYTE_ARRAY_OVERHEAD;
public final static int OBJECT_OVERHEAD;
public final static int ARRAY_ITEM_OVERHEAD;
public final static int HASHMAP_OVERHEAD;
public final static int HASHMAP_ENTRY_OVERHEAD;
public final static int HASHSET_OVERHEAD;
public final static int HASHSET_ENTRY_OVERHEAD;
public final static int TWOHASHMAPS_OVERHEAD;
public final static int TREEMAP_OVERHEAD;
public final static int TREEMAP_ENTRY_OVERHEAD;
public final static int LN_OVERHEAD;
public final static int DUPCOUNTLN_OVERHEAD;
public final static int BIN_FIXED_OVERHEAD;
public final static int DIN_FIXED_OVERHEAD;
public final static int DBIN_FIXED_OVERHEAD;
public final static int IN_FIXED_OVERHEAD;
public final static int KEY_OVERHEAD;
public final static int LOCK_OVERHEAD;
public final static int LOCKINFO_OVERHEAD;
public final static int TXN_OVERHEAD;
public final static int CHECKPOINT_REFERENCE_SIZE;
public final static int UTILIZATION_PROFILE_ENTRY;
public final static int TFS_LIST_INITIAL_OVERHEAD;
public final static int TFS_LIST_SEGMENT_OVERHEAD;
public final static int LN_INFO_OVERHEAD;
public final static int LONG_LIST_PER_ITEM_OVERHEAD;
private final static String JVM_ARCH_PROPERTY = "sun.arch.data.model";
private final static String FORCE_JVM_ARCH = "je.forceJVMArch";
static {
boolean is64 = false;
boolean isJVM14 = (LatchSupport.getJava5LatchClass() == null);//TODO default value necessary
String overrideArch = System.getProperty(FORCE_JVM_ARCH);
try {
if (overrideArch == null) {
String arch = System.getProperty(JVM_ARCH_PROPERTY);
if (arch != null) {
is64 = Integer.parseInt(arch) == 64;
}
} else {
is64 = Integer.parseInt(overrideArch) == 64;
}
} catch (NumberFormatException NFE) {
NFE.printStackTrace(System.err);
}
if (is64) {
if (isJVM14) {
RuntimeException RE = new RuntimeException
("1.4 based 64 bit JVM not supported");
RE.printStackTrace(System.err);
throw RE;
}
LONG_OVERHEAD = LONG_OVERHEAD_64;
BYTE_ARRAY_OVERHEAD = BYTE_ARRAY_OVERHEAD_64;
OBJECT_OVERHEAD = OBJECT_OVERHEAD_64;
ARRAY_ITEM_OVERHEAD = ARRAY_ITEM_OVERHEAD_64;
HASHMAP_OVERHEAD = HASHMAP_OVERHEAD_64;
HASHMAP_ENTRY_OVERHEAD = HASHMAP_ENTRY_OVERHEAD_64;
HASHSET_OVERHEAD = HASHSET_OVERHEAD_64;
HASHSET_ENTRY_OVERHEAD = HASHSET_ENTRY_OVERHEAD_64;
TWOHASHMAPS_OVERHEAD = TWOHASHMAPS_OVERHEAD_64;
TREEMAP_OVERHEAD = TREEMAP_OVERHEAD_64;
TREEMAP_ENTRY_OVERHEAD = TREEMAP_ENTRY_OVERHEAD_64;
LN_OVERHEAD = LN_OVERHEAD_64;
DUPCOUNTLN_OVERHEAD = DUPCOUNTLN_OVERHEAD_64;
BIN_FIXED_OVERHEAD = BIN_FIXED_OVERHEAD_64_15;
DIN_FIXED_OVERHEAD = DIN_FIXED_OVERHEAD_64_15;
DBIN_FIXED_OVERHEAD = DBIN_FIXED_OVERHEAD_64_15;
IN_FIXED_OVERHEAD = IN_FIXED_OVERHEAD_64_15;
TXN_OVERHEAD = TXN_OVERHEAD_64_15;
CHECKPOINT_REFERENCE_SIZE = CHECKPOINT_REFERENCE_SIZE_64_15;
KEY_OVERHEAD = KEY_OVERHEAD_64;
LOCK_OVERHEAD = LOCK_OVERHEAD_64;
LOCKINFO_OVERHEAD = LOCKINFO_OVERHEAD_64;
UTILIZATION_PROFILE_ENTRY = UTILIZATION_PROFILE_ENTRY_64;
TFS_LIST_INITIAL_OVERHEAD = TFS_LIST_INITIAL_OVERHEAD_64;
TFS_LIST_SEGMENT_OVERHEAD = TFS_LIST_SEGMENT_OVERHEAD_64;
LN_INFO_OVERHEAD = LN_INFO_OVERHEAD_64;
LONG_LIST_PER_ITEM_OVERHEAD = LONG_LIST_PER_ITEM_OVERHEAD_64;
} else {
LONG_OVERHEAD = LONG_OVERHEAD_32;
BYTE_ARRAY_OVERHEAD = BYTE_ARRAY_OVERHEAD_32;
OBJECT_OVERHEAD = OBJECT_OVERHEAD_32;
ARRAY_ITEM_OVERHEAD = ARRAY_ITEM_OVERHEAD_32;
HASHMAP_OVERHEAD = HASHMAP_OVERHEAD_32;
HASHMAP_ENTRY_OVERHEAD = HASHMAP_ENTRY_OVERHEAD_32;
HASHSET_OVERHEAD = HASHSET_OVERHEAD_32;
HASHSET_ENTRY_OVERHEAD = HASHSET_ENTRY_OVERHEAD_32;
TWOHASHMAPS_OVERHEAD = TWOHASHMAPS_OVERHEAD_32;
TREEMAP_OVERHEAD = TREEMAP_OVERHEAD_32;
TREEMAP_ENTRY_OVERHEAD = TREEMAP_ENTRY_OVERHEAD_32;
LN_OVERHEAD = LN_OVERHEAD_32;
DUPCOUNTLN_OVERHEAD = DUPCOUNTLN_OVERHEAD_32;
if (isJVM14) {
BIN_FIXED_OVERHEAD = BIN_FIXED_OVERHEAD_32_14;
DIN_FIXED_OVERHEAD = DIN_FIXED_OVERHEAD_32_14;
DBIN_FIXED_OVERHEAD = DBIN_FIXED_OVERHEAD_32_14;
IN_FIXED_OVERHEAD = IN_FIXED_OVERHEAD_32_14;
TXN_OVERHEAD = TXN_OVERHEAD_32_14;
CHECKPOINT_REFERENCE_SIZE = CHECKPOINT_REFERENCE_SIZE_32_14;
} else {
BIN_FIXED_OVERHEAD = BIN_FIXED_OVERHEAD_32_15;
DIN_FIXED_OVERHEAD = DIN_FIXED_OVERHEAD_32_15;
DBIN_FIXED_OVERHEAD = DBIN_FIXED_OVERHEAD_32_15;
IN_FIXED_OVERHEAD = IN_FIXED_OVERHEAD_32_15;
TXN_OVERHEAD = TXN_OVERHEAD_32_15;
CHECKPOINT_REFERENCE_SIZE = CHECKPOINT_REFERENCE_SIZE_32_15;
}
KEY_OVERHEAD = KEY_OVERHEAD_32;
LOCK_OVERHEAD = LOCK_OVERHEAD_32;
LOCKINFO_OVERHEAD = LOCKINFO_OVERHEAD_32;
UTILIZATION_PROFILE_ENTRY = UTILIZATION_PROFILE_ENTRY_32;
TFS_LIST_INITIAL_OVERHEAD = TFS_LIST_INITIAL_OVERHEAD_32;
TFS_LIST_SEGMENT_OVERHEAD = TFS_LIST_SEGMENT_OVERHEAD_32;
LN_INFO_OVERHEAD = LN_INFO_OVERHEAD_32;
LONG_LIST_PER_ITEM_OVERHEAD = LONG_LIST_PER_ITEM_OVERHEAD_32;
}
}
/* public for unit tests. */
public final static long MIN_MAX_MEMORY_SIZE = 96 * 1024;
public final static String MIN_MAX_MEMORY_SIZE_STRING =
Long.toString(MIN_MAX_MEMORY_SIZE);
private final static long N_64MB = (1 << 26);
/*
* Note that this class contains long fields that are accessed by multiple
* threads, and access to these fields is intentionally not synchronized.
* Although inaccuracies may result, correcting them is not worth the cost
* of synchronizing every time we adjust the treeMemoryUsage or
* miscMemoryUsage.
*/
/*
* Amount of memory cached for tree objects.
*/
private long treeMemoryUsage;
/*
* Amount of memory cached for Txn and other objects.
*/
private long miscMemoryUsage;
/*
* Used to protect treeMemoryUsage and miscMemoryUsage updates.
*/
private Object memoryUsageSynchronizer = new Object();
/*
* Number of lock tables (cache of EnvironmentParams.N_LOCK_TABLES).
*/
private int nLockTables;
/*
* Amount of memory cached for locks. Protected by the
* LockManager.lockTableLatches[lockTableIndex]. Individual elements of
* array may be negative, but the sum will be >= 0.
*/
private long[] lockMemoryUsage;
/*
* Memory available to JE, based on je.maxMemory and the memory available
* to this process.
*/
private long maxMemory;
private long criticalThreshold; // experimental mark for sync eviction.
/* Memory available to log buffers. */
private long logBufferBudget;
/* Maximum allowed use of the misc budget by the UtilizationTracker. */
private long trackerBudget;
/*
* Memory to hold internal nodes and misc memory (locks), controlled by the
* evictor. Does not include the log buffers.
*/
private long cacheBudget;
/*
* Overheads that are a function of node capacity.
*/
private long inOverhead;
private long binOverhead;
private long dinOverhead;
private long dbinOverhead;
private EnvironmentImpl envImpl;
MemoryBudget(EnvironmentImpl envImpl,
DbConfigManager configManager)
throws DatabaseException {
this.envImpl = envImpl;
/* Request notification of mutable property changes. */
envImpl.addConfigObserver(this);
/* Peform first time budget initialization. */
reset(configManager);
/*
* Calculate IN and BIN overheads, which are a function of
* capacity. These values are stored in this class so that they can be
* calculated once per environment. The logic to do the calculations is
* left in the respective node classes so it can be done properly in
* the domain of those objects.
*/
inOverhead = IN.computeOverhead(configManager);
binOverhead = BIN.computeOverhead(configManager);
dinOverhead = DIN.computeOverhead(configManager);
dbinOverhead = DBIN.computeOverhead(configManager);
}
/**
* Respond to config updates.
*/
public void envConfigUpdate(DbConfigManager configManager)
throws DatabaseException {
/*
* Reinitialize the cache budget and the log buffer pool, in that
* order. Do not reset the log buffer pool if the log buffer budget
* hasn't changed, since that is expensive and may cause I/O.
*/
long oldLogBufferBudget = logBufferBudget;
reset(configManager);
if (oldLogBufferBudget != logBufferBudget) {
envImpl.getLogManager().resetPool(configManager);
}
}
/**
* Initialize at construction time and when the cache is resized.
*/
private void reset(DbConfigManager configManager)
throws DatabaseException {
/*
* Calculate the total memory allotted to JE.
* 1. If je.maxMemory is specified, use that. Check that it's
* not more than the jvm memory.
* 2. Otherwise, take je.maxMemoryPercent * JVM max memory.
*/
long newMaxMemory =
configManager.getLong(EnvironmentParams.MAX_MEMORY);
long jvmMemory = getRuntimeMaxMemory();
if (newMaxMemory != 0) {
/* Application specified a cache size number, validate it. */
if (jvmMemory < newMaxMemory) {
throw new IllegalArgumentException
(EnvironmentParams.MAX_MEMORY.getName() +
" has a value of " + newMaxMemory +
" but the JVM is only configured for " +
jvmMemory +
". Consider using je.maxMemoryPercent.");
}
if (newMaxMemory < MIN_MAX_MEMORY_SIZE) {
throw new IllegalArgumentException
(EnvironmentParams.MAX_MEMORY.getName() +
" is " + newMaxMemory +
" which is less than the minimum: " +
MIN_MAX_MEMORY_SIZE);
}
} else {
/*
* When no explicit cache size is specified and the JVM memory size
* is unknown, assume a default sized (64 MB) heap. This produces
* a reasonable cache size when no heap size is known.
*/
if (jvmMemory == Long.MAX_VALUE) {
jvmMemory = N_64MB;
}
/* Use the configured percentage of the JVM memory size. */
int maxMemoryPercent =
configManager.getInt(EnvironmentParams.MAX_MEMORY_PERCENT);
newMaxMemory = (maxMemoryPercent * jvmMemory) / 100;
}
/*
* Calculate the memory budget for log buffering. If the LOG_MEM_SIZE
* parameter is not set, start by using 7% (1/16th) of the cache
* size. If it is set, use that explicit setting.
*
* No point in having more log buffers than the maximum size. If
* this starting point results in overly large log buffers,
* reduce the log buffer budget again.
*/
long newLogBufferBudget =
configManager.getLong(EnvironmentParams.LOG_MEM_SIZE);
if (newLogBufferBudget == 0) {
newLogBufferBudget = newMaxMemory >> 4;
} else if (newLogBufferBudget > newMaxMemory / 2) {
newLogBufferBudget = newMaxMemory / 2;
}
/*
* We have a first pass at the log buffer budget. See what
* size log buffers result. Don't let them be too big, it would
* be a waste.
*/
int numBuffers =
configManager.getInt(EnvironmentParams.NUM_LOG_BUFFERS);
long startingBufferSize = newLogBufferBudget / numBuffers;
int logBufferSize =
configManager.getInt(EnvironmentParams.LOG_BUFFER_MAX_SIZE);
if (startingBufferSize > logBufferSize) {
startingBufferSize = logBufferSize;
newLogBufferBudget = numBuffers * startingBufferSize;
} else if (startingBufferSize <
EnvironmentParams.MIN_LOG_BUFFER_SIZE) {
startingBufferSize = EnvironmentParams.MIN_LOG_BUFFER_SIZE;
newLogBufferBudget = numBuffers * startingBufferSize;
}
long newCriticalThreshold =
(newMaxMemory *
envImpl.getConfigManager().getInt
(EnvironmentParams.EVICTOR_CRITICAL_PERCENTAGE))/100;
long newTrackerBudget =
(newMaxMemory *
envImpl.getConfigManager().getInt
(EnvironmentParams.CLEANER_DETAIL_MAX_MEMORY_PERCENTAGE))/100;
/*
* If all has gone well, update the budget fields. Once the log buffer
* budget is determined, the remainder of the memory is left for tree
* nodes.
*/
maxMemory = newMaxMemory;
criticalThreshold = newCriticalThreshold;
logBufferBudget = newLogBufferBudget;
trackerBudget = true?newTrackerBudget:newMaxMemory;
cacheBudget = newMaxMemory - newLogBufferBudget;
nLockTables =
configManager.getInt(EnvironmentParams.N_LOCK_TABLES);
lockMemoryUsage = new long[nLockTables];
}
/**
* Returns Runtime.maxMemory(), accounting for a MacOS bug.
* May return Long.MAX_VALUE if there is no inherent limit.
* Used by unit tests as well as by this class.
*/
public static long getRuntimeMaxMemory() {
/* Runtime.maxMemory is unreliable on MacOS Java 1.4.2. */
if ("Mac OS X".equals(System.getProperty("os.name"))) {
String jvmVersion = System.getProperty("java.version");
if (jvmVersion != null && jvmVersion.startsWith("1.4.2")) {
return Long.MAX_VALUE; /* Undetermined heap size. */
}
}
return Runtime.getRuntime().maxMemory();
}
/**
* Initialize the starting environment memory state
*/
void initCacheMemoryUsage()
throws DatabaseException {
synchronized (memoryUsageSynchronizer) {
treeMemoryUsage = calcTreeCacheUsage();
}
assert LatchSupport.countLatchesHeld() == 0;
}
/**
* Public for testing.
*/
public long calcTreeCacheUsage()
throws DatabaseException {
long totalSize = 0;
INList inList = envImpl.getInMemoryINs();
inList.latchMajor();
try {
Iterator iter = inList.iterator();
while (iter.hasNext()) {
IN in = (IN) iter.next();
long size = in.getInMemorySize();
totalSize += size;
}
} finally {
inList.releaseMajorLatch();
}
return totalSize;
}
/**
* Update the environment wide tree memory count, wake up the evictor if
* necessary.
* @param increment note that increment may be negative.
*/
public void updateTreeMemoryUsage(long increment) {
synchronized (memoryUsageSynchronizer) {
treeMemoryUsage += increment;
}
if (getCacheMemoryUsage() > cacheBudget) {
envImpl.alertEvictor();
}
}
/**
* Update the environment wide misc memory count, wake up the evictor if
* necessary.
* @param increment note that increment may be negative.
*/
public void updateMiscMemoryUsage(long increment) {
synchronized (memoryUsageSynchronizer) {
miscMemoryUsage += increment;
}
if (getCacheMemoryUsage() > cacheBudget) {
envImpl.alertEvictor();
}
}
public void updateLockMemoryUsage(long increment, int lockTableIndex) {
lockMemoryUsage[lockTableIndex] += increment;
if (getCacheMemoryUsage() > cacheBudget) {
envImpl.alertEvictor();
}
}
public long accumulateNewUsage(IN in, long newSize) {
return in.getInMemorySize() + newSize;
}
public void refreshTreeMemoryUsage(long newSize) {
synchronized (memoryUsageSynchronizer) {
treeMemoryUsage = newSize;
}
}
public long getCacheMemoryUsage() {
long accLockMemoryUsage = 0;
if (nLockTables == 1) {
accLockMemoryUsage = lockMemoryUsage[0];
} else {
for (int i = 0; i < nLockTables; i++) {
accLockMemoryUsage += lockMemoryUsage[i];
}
}
return treeMemoryUsage + miscMemoryUsage + accLockMemoryUsage;
}
/**
* Used for unit testing.
*/
public long getTreeMemoryUsage() {
return treeMemoryUsage;
}
public long getLogBufferBudget() {
return logBufferBudget;
}
public long getTrackerBudget() {
return trackerBudget;
}
public long getMaxMemory() {
return maxMemory;
}
public long getCriticalThreshold() {
return criticalThreshold;
}
public long getCacheBudget() {
return cacheBudget;
}
public long getINOverhead() {
return inOverhead;
}
public long getBINOverhead() {
return binOverhead;
}
public long getDINOverhead() {
return dinOverhead;
}
public long getDBINOverhead() {
return dbinOverhead;
}
/**
* Returns the memory size occupied by a byte array of a given length.
*/
public static int byteArraySize(int arrayLen) {
/*
* BYTE_ARRAY_OVERHEAD accounts for 4 bytes of data. Data larger than
* 4 bytes is allocated in 8 byte increments.
*/
int size = BYTE_ARRAY_OVERHEAD;
if (arrayLen > 4) {
size += ((arrayLen - 4 + 7) / 8) * 8;
}
return size;
}
void loadStats(StatsConfig config, EnvironmentStats stats) {
stats.setCacheDataBytes(getCacheMemoryUsage());
}
}